package com.qf.jedis2301.filter;

import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

/**
 * @Author UNIQ7xi
 * @Date 2023/6/19 19:10
 * @Version v1.8
 **/
@Component
public class IpLimitFilter implements Filter {
    private static final int MAX_REQUEST_COUNT = 10;   //最大请求次数
    private static final int EXPIRE_TIME = 3;          //限流时间
    private static final int BLACKLIST_COUNT = 3;      //黑名单连续违规次数

    private Jedis jedis;
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        //连接redis
        jedis = new Jedis("192.168.1.61",6379);
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
        String ip = getRealIp(httpRequest);
        if (isInBlackList(ip)){
            servletResponse.getWriter().write("IP被限制,请联系管理员");
            return;
        }
        String key = "ip"+ip;
        long count = jedis.incr(key);
        jedis.expire(key,EXPIRE_TIME);
        if (count > MAX_REQUEST_COUNT) { //超过最大请求次数
            jedis.sadd("blacklist", ip); //将该IP地址加入黑名单
            servletResponse.getWriter().write("访问过于频繁！");
            return;
        }
        filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override
    public void destroy() {
        jedis.close();
    }

    private String getRealIp(HttpServletRequest request){
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    //判断是否在黑名单中
    private boolean isInBlackList(String ip) {
        long count = jedis.scard("blacklist");
        if (count >= BLACKLIST_COUNT && jedis.sismember("blacklist", ip)) {
            return true;
        }
        return false;
    }
}
